// System process calls implementation
// Author: $USER_NAME$
// Date: $DATE$
// Description: 实现与进程管理相关的系统调用，包括进程创建、终止、等待、内存分配等核心功能

#include "types.h"
#include "riscv.h"
#include "defs.h"
#include "date.h"
#include "param.h"
#include "memlayout.h"
#include "spinlock.h"
#include "proc.h"

// 退出系统调用
// 参数: 退出状态码
// 返回值: 不返回（进程终止）
uint64
sys_exit(void)
{
  int n;
  if(argint(0, &n) < 0)
    return -1;
  exit(n);
  return 0;  // not reached
}

// 获取当前进程PID系统调用
// 返回值: 当前进程的PID
uint64
sys_getpid(void)
{
  return myproc()->pid;
}

// 创建子进程系统调用（fork）
// 返回值: 在父进程中返回子进程PID，在子进程中返回0，失败返回-1
uint64
sys_fork(void)
{
  return fork();
}

// 等待子进程结束系统调用
// 参数p: 指向存储子进程退出状态的地址
// 返回值: 结束的子进程PID，失败返回-1
uint64
sys_wait(void)
{
  uint64 p;
  if(argaddr(0, &p) < 0)
    return -1;
  return wait(p);
}

// 调整进程堆大小系统调用（sbrk）
// 参数: 要增加或减少的字节数
// 返回值: 调整前的程序中断点地址，失败返回-1
uint64
sys_sbrk(void)
{
  int n;

  if(argint(0, &n) < 0)
    return -1;
  struct proc *p = myproc();
  uint64  addr = p->sz;
  uint64 newSize = addr + n;
  if (newSize >= MAXVA)
    return addr;
  if (n < 0) {
    if (newSize > addr) {
      newSize = 0;
      uvmunmap(p->pagetable, 0, PGROUNDUP(addr), 1);
    } else {
      uvmunmap(p->pagetable, PGROUNDUP(newSize),
               (PGROUNDUP(addr) - PGROUNDUP(newSize)), 1);
    }
  }
  p->sz = newSize;
  return addr;
}

// 进程睡眠系统调用
// 参数: 要睡眠的时钟周期数
// 返回值: 成功返回0，被杀死返回-1
uint64
sys_sleep(void)
{
  int n;
  uint ticks0;

  if(argint(0, &n) < 0)
    return -1;
  acquire(&tickslock);
  ticks0 = ticks;
  while(ticks - ticks0 < n){
    if(myproc()->killed){
      release(&tickslock);
      return -1;
    }
    sleep(&ticks, &tickslock);
  }
  release(&tickslock);
  return 0;
}

// 杀死指定进程系统调用
// 参数: 要杀死的进程PID
// 返回值: 成功返回0，失败返回-1
uint64
sys_kill(void)
{
  int pid;

  if(argint(0, &pid) < 0)
    return -1;
  return kill(pid);
}

// return how many clock tick interrupts have occurred
// since start.
// 获取系统启动以来的时钟周期数
// 返回值: 时钟周期数
uint64
sys_uptime(void)
{
  uint xticks;

  acquire(&tickslock);
  xticks = ticks;
  release(&tickslock);
  return xticks;
}